package com.hsd.znsh.service.impl;

import com.hsd.znsh.entity.Property;
import com.hsd.znsh.entity.Sensor;
import com.hsd.znsh.entity.SensorData;
import com.hsd.znsh.entity.SensorTypeProperty;
import com.hsd.znsh.pojo.query.SensorInfoQuery;
import com.hsd.znsh.repository.PropertyRepository;
import com.hsd.znsh.repository.SensorDataRepository;
import com.hsd.znsh.repository.SensorRepository;
import com.hsd.znsh.repository.SensorTypePropertyRepository;
import com.hsd.znsh.service.AsyncService;
import com.hsd.znsh.service.BaseService;
import com.hsd.znsh.service.SensorDataService;
import com.hsd.znsh.utils.BeanUtil;
import com.hsd.znsh.utils.DateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;
import org.springframework.util.concurrent.ListenableFuture;

import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.CountDownLatch;

/*
 * @auther: wangjiacai
 *
 * @create: 2018-04-27 13:45:24
 */
@Service
public class SensorDataServiceImpl extends BaseServiceImpl implements SensorDataService {

    @Autowired
    private SensorDataRepository sensorDataRepository;

    @Autowired
    private SensorRepository sensorRepository;

    @Autowired
    private SensorTypePropertyRepository sensorTypePropertyRepository;

    @Autowired
    private PropertyRepository propertyRepository;

    @Autowired
    private AsyncService asyncService;

    @Override
    public Map<String,Object>  getSensorData(String sensorSn,Integer bh) {
        Sensor sensor=sensorRepository.findBySensorSn(sensorSn);
        SensorTypeProperty sensorTypeProperty=sensorTypePropertyRepository.findBySensorTypeIdAndBh(sensor.getSensorTypeId(),bh);
        SensorData sensorData=sensorDataRepository.findBySensorSnAndTimeAndPropertyId(
                sensorSn,sensor.getTime(),sensorTypeProperty.getPropertyId());
        Property property=propertyRepository.findOne(sensorTypeProperty.getPropertyId());
        Map<String,Object> map= BeanUtil.objectToMap(sensorData);
        map.putAll(BeanUtil.objectToMap(property));
        return map;
    }

    @Override
    public List<SensorData> getSensorHistoryData(SensorInfoQuery sensorInfoQuery) {
        String sensorSn=sensorInfoQuery.getSensorSn();
        Sensor sensor=sensorRepository.findBySensorSn(sensorSn);
        SensorTypeProperty sensorTypeProperty=sensorTypePropertyRepository.findBySensorTypeIdAndBh(sensor.getSensorTypeId(),sensorInfoQuery.getBh());

        LocalDateTime now=LocalDateTime.now();
        LocalDateTime start=now.minusHours(sensorInfoQuery.getTotalTime());
        long startTime=System.currentTimeMillis();


        Integer n=1;
        Integer intervalTime=sensorInfoQuery.getTotalTime()*60/n;

        if(intervalTime<sensorInfoQuery.getIntervals()){
            intervalTime=sensorInfoQuery.getIntervals();
            n=sensorInfoQuery.getTotalTime()*60/intervalTime;
        }

        CountDownLatch countDownLatch=new CountDownLatch(n);
        List<SensorData> allSensorData=Collections.synchronizedList(new ArrayList<>());
        while(n>0) {
            asyncService.findSensorDataByTimeBetween(sensorSn,sensorTypeProperty.getPropertyId(),
                    start,start.plusMinutes(intervalTime),sensorInfoQuery.getIntervals())
            .addCallback(
                    list -> onSuccess(allSensorData,list,countDownLatch),
                    err -> onError(err,countDownLatch));
            start=start.plusMinutes(intervalTime);
            n--;
        }
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
            return allSensorData;
        }

        /*Collections.sort(allSensorData, new Comparator<SensorData>() {
            @Override
            public int compare(SensorData o1, SensorData o2) {
                if(o1.getTime().getTime()-o2.getTime().getTime()>0){
                    return 1;
                }else if(o1.getTime().getTime()-o2.getTime().getTime()<0){
                    return -1;
                }
                return 0;
            }
        });*/
        System.out.println("time:"+(System.currentTimeMillis()-startTime)/1000);
        return allSensorData;
    }

    private void onSuccess(List<SensorData> allSensorData,List<SensorData> list,CountDownLatch countDownLatch){
        allSensorData.addAll(list);
        countDownLatch.countDown();
    }

    private void onError(Throwable throwable,CountDownLatch countDownLatch){
        throwable.printStackTrace();
        countDownLatch.countDown();
    }

}
